1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import com.google.common.annotations.Beta;
20  import com.google.common.annotations.GwtCompatible;
21  import com.google.common.base.Objects;
22  
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.annotation.Nullable;
29  
30  /**
31   * A map which forwards all its method calls to another map. Subclasses should
32   * override one or more methods to modify the behavior of the backing map as
33   * desired per the <a
34   * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
35   *
36   * <p><i>Warning:</i> The methods of {@code ForwardingMap} forward
37   * <i>indiscriminately</i> to the methods of the delegate. For example,
38   * overriding {@link #put} alone <i>will not</i> change the behavior of {@link
39   * #putAll}, which can lead to unexpected behavior. In this case, you should
40   * override {@code putAll} as well, either providing your own implementation, or
41   * delegating to the provided {@code standardPutAll} method.
42   *
43   * <p>Each of the {@code standard} methods, where appropriate, use {@link
44   * Objects#equal} to test equality for both keys and values. This may not be
45   * the desired behavior for map implementations that use non-standard notions of
46   * key equality, such as a {@code SortedMap} whose comparator is not consistent
47   * with {@code equals}.
48   *
49   * <p>The {@code standard} methods and the collection views they return are not
50   * guaranteed to be thread-safe, even when all of the methods that they depend
51   * on are thread-safe.
52   *
53   * @author Kevin Bourrillion
54   * @author Jared Levy
55   * @author Louis Wasserman
56   * @since 2.0 (imported from Google Collections Library)
57   */
58  @GwtCompatible
59  public abstract class ForwardingMap<K, V> extends ForwardingObject
60      implements Map<K, V> {
61    // TODO(user): identify places where thread safety is actually lost
62  
63    /** Constructor for use by subclasses. */
64    protected ForwardingMap() {}
65  
66    @Override protected abstract Map<K, V> delegate();
67  
68    @Override
69    public int size() {
70      return delegate().size();
71    }
72  
73    @Override
74    public boolean isEmpty() {
75      return delegate().isEmpty();
76    }
77  
78    @Override
79    public V remove(Object object) {
80      return delegate().remove(object);
81    }
82  
83    @Override
84    public void clear() {
85      delegate().clear();
86    }
87  
88    @Override
89    public boolean containsKey(@Nullable Object key) {
90      return delegate().containsKey(key);
91    }
92  
93    @Override
94    public boolean containsValue(@Nullable Object value) {
95      return delegate().containsValue(value);
96    }
97  
98    @Override
99    public V get(@Nullable Object key) {
100     return delegate().get(key);
101   }
102 
103   @Override
104   public V put(K key, V value) {
105     return delegate().put(key, value);
106   }
107 
108   @Override
109   public void putAll(Map<? extends K, ? extends V> map) {
110     delegate().putAll(map);
111   }
112 
113   @Override
114   public Set<K> keySet() {
115     return delegate().keySet();
116   }
117 
118   @Override
119   public Collection<V> values() {
120     return delegate().values();
121   }
122 
123   @Override
124   public Set<Entry<K, V>> entrySet() {
125     return delegate().entrySet();
126   }
127 
128   @Override public boolean equals(@Nullable Object object) {
129     return object == this || delegate().equals(object);
130   }
131 
132   @Override public int hashCode() {
133     return delegate().hashCode();
134   }
135 
136   /**
137    * A sensible definition of {@link #putAll(Map)} in terms of {@link
138    * #put(Object, Object)}. If you override {@link #put(Object, Object)}, you
139    * may wish to override {@link #putAll(Map)} to forward to this
140    * implementation.
141    *
142    * @since 7.0
143    */
144   protected void standardPutAll(Map<? extends K, ? extends V> map) {
145     Maps.putAllImpl(this, map);
146   }
147 
148   /**
149    * A sensible, albeit inefficient, definition of {@link #remove} in terms of
150    * the {@code iterator} method of {@link #entrySet}. If you override {@link
151    * #entrySet}, you may wish to override {@link #remove} to forward to this
152    * implementation.
153    *
154    * <p>Alternately, you may wish to override {@link #remove} with {@code
155    * keySet().remove}, assuming that approach would not lead to an infinite
156    * loop.
157    *
158    * @since 7.0
159    */
160   @Beta protected V standardRemove(@Nullable Object key) {
161     Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
162     while (entryIterator.hasNext()) {
163       Entry<K, V> entry = entryIterator.next();
164       if (Objects.equal(entry.getKey(), key)) {
165         V value = entry.getValue();
166         entryIterator.remove();
167         return value;
168       }
169     }
170     return null;
171   }
172 
173   /**
174    * A sensible definition of {@link #clear} in terms of the {@code iterator}
175    * method of {@link #entrySet}. In many cases, you may wish to override
176    * {@link #clear} to forward to this implementation.
177    *
178    * @since 7.0
179    */
180   protected void standardClear() {
181     Iterators.clear(entrySet().iterator());
182   }
183 
184   /**
185    * A sensible implementation of {@link Map#keySet} in terms of the following
186    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
187    * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove}, {@link
188    * ForwardingMap#size}, and the {@link Set#iterator} method of {@link
189    * ForwardingMap#entrySet}. In many cases, you may wish to override {@link
190    * ForwardingMap#keySet} to forward to this implementation or a subclass
191    * thereof.
192    *
193    * @since 10.0
194    */
195   @Beta
196   protected class StandardKeySet extends Maps.KeySet<K, V> {
197     /** Constructor for use by subclasses. */
198     public StandardKeySet() {
199       super(ForwardingMap.this);
200     }
201   }
202 
203   /**
204    * A sensible, albeit inefficient, definition of {@link #containsKey} in terms
205    * of the {@code iterator} method of {@link #entrySet}. If you override {@link
206    * #entrySet}, you may wish to override {@link #containsKey} to forward to
207    * this implementation.
208    *
209    * @since 7.0
210    */
211   @Beta protected boolean standardContainsKey(@Nullable Object key) {
212     return Maps.containsKeyImpl(this, key);
213   }
214 
215   /**
216    * A sensible implementation of {@link Map#values} in terms of the following
217    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue},
218    * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the {@link
219    * Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases, you
220    * may wish to override {@link ForwardingMap#values} to forward to this
221    * implementation or a subclass thereof.
222    *
223    * @since 10.0
224    */
225   @Beta
226   protected class StandardValues extends Maps.Values<K, V> {
227     /** Constructor for use by subclasses. */
228     public StandardValues() {
229       super(ForwardingMap.this);
230     }
231   }
232 
233   /**
234    * A sensible definition of {@link #containsValue} in terms of the {@code
235    * iterator} method of {@link #entrySet}. If you override {@link #entrySet},
236    * you may wish to override {@link #containsValue} to forward to this
237    * implementation.
238    *
239    * @since 7.0
240    */
241   protected boolean standardContainsValue(@Nullable Object value) {
242     return Maps.containsValueImpl(this, value);
243   }
244 
245   /**
246    * A sensible implementation of {@link Map#entrySet} in terms of the following
247    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
248    * {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty}, {@link
249    * ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases, you
250    * may wish to override {@link #entrySet} to forward to this implementation
251    * or a subclass thereof.
252    *
253    * @since 10.0
254    */
255   @Beta
256   protected abstract class StandardEntrySet extends Maps.EntrySet<K, V> {
257     /** Constructor for use by subclasses. */
258     public StandardEntrySet() {}
259 
260     @Override
261     Map<K, V> map() {
262       return ForwardingMap.this;
263     }
264   }
265 
266   /**
267    * A sensible definition of {@link #isEmpty} in terms of the {@code iterator}
268    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
269    * wish to override {@link #isEmpty} to forward to this implementation.
270    *
271    * @since 7.0
272    */
273   protected boolean standardIsEmpty() {
274     return !entrySet().iterator().hasNext();
275   }
276 
277   /**
278    * A sensible definition of {@link #equals} in terms of the {@code equals}
279    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
280    * wish to override {@link #equals} to forward to this implementation.
281    *
282    * @since 7.0
283    */
284   protected boolean standardEquals(@Nullable Object object) {
285     return Maps.equalsImpl(this, object);
286   }
287 
288   /**
289    * A sensible definition of {@link #hashCode} in terms of the {@code iterator}
290    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
291    * wish to override {@link #hashCode} to forward to this implementation.
292    *
293    * @since 7.0
294    */
295   protected int standardHashCode() {
296     return Sets.hashCodeImpl(entrySet());
297   }
298 
299   /**
300    * A sensible definition of {@link #toString} in terms of the {@code iterator}
301    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
302    * wish to override {@link #toString} to forward to this implementation.
303    *
304    * @since 7.0
305    */
306   protected String standardToString() {
307     return Maps.toStringImpl(this);
308   }
309 }